From 6891f401107ce400729de86f75e7160d99c3f1cf Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 15 Nov 2020 21:52:07 -0500 Subject: [PATCH] modelbutton: Fix keynav for check and radio The expected behavior when activating check or radio menuitems via keynav is that Space toggles the item but keeps the menu open, while Return toggles the item and closes the menu. --- gtk/gtkmodelbutton.c | 49 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/gtk/gtkmodelbutton.c b/gtk/gtkmodelbutton.c index 9efed319aa..501dc5e087 100644 --- a/gtk/gtkmodelbutton.c +++ b/gtk/gtkmodelbutton.c @@ -179,6 +179,7 @@ struct _GtkModelButton guint active : 1; guint centered : 1; guint iconic : 1; + guint keep_open : 1; }; typedef struct _GtkModelButtonClass GtkModelButtonClass; @@ -1044,7 +1045,7 @@ gtk_model_button_clicked (GtkModelButton *self) gtk_popover_menu_set_open_submenu (menu, submenu); gtk_popover_menu_set_parent_menu (GTK_POPOVER_MENU (submenu), GTK_WIDGET (menu)); } - else if (self->role == GTK_BUTTON_ROLE_NORMAL) + else if (!self->keep_open) { GtkWidget *popover; @@ -1057,6 +1058,20 @@ gtk_model_button_clicked (GtkModelButton *self) gtk_action_helper_activate (self->action_helper); } +static gboolean +toggle_cb (GtkWidget *widget, + GVariant *args, + gpointer user_data) +{ + GtkModelButton *self = GTK_MODEL_BUTTON (widget); + + self->keep_open = self->role != GTK_BUTTON_ROLE_NORMAL; + g_signal_emit (widget, signals[SIGNAL_CLICKED], 0); + self->keep_open = FALSE; + + return TRUE; +} + static void gtk_model_button_finalize (GObject *object) { @@ -1128,6 +1143,14 @@ gtk_model_button_class_init (GtkModelButtonClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); + GtkShortcutAction *action; + guint activate_keyvals[] = { + GDK_KEY_Return, GDK_KEY_ISO_Enter, GDK_KEY_KP_Enter + }; + guint toggle_keyvals[] = { + GDK_KEY_space, GDK_KEY_KP_Space + }; + int i; object_class->dispose = gtk_model_button_dispose; object_class->finalize = gtk_model_button_finalize; @@ -1277,6 +1300,30 @@ gtk_model_button_class_init (GtkModelButtonClass *class) gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT); gtk_widget_class_set_css_name (widget_class, I_("modelbutton")); gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_MENU_ITEM); + + action = gtk_signal_action_new ("clicked"); + for (i = 0; i < G_N_ELEMENTS (activate_keyvals); i++) + { + GtkShortcut *shortcut; + + shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (activate_keyvals[i], 0), + g_object_ref (action)); + gtk_widget_class_add_shortcut (widget_class, shortcut); + g_object_unref (shortcut); + } + g_object_unref (action); + + action = gtk_callback_action_new (toggle_cb, NULL, NULL); + for (i = 0; i < G_N_ELEMENTS (toggle_keyvals); i++) + { + GtkShortcut *shortcut; + + shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (toggle_keyvals[i], 0), + g_object_ref (action)); + gtk_widget_class_add_shortcut (widget_class, shortcut); + g_object_unref (shortcut); + } + g_object_unref (action); } static void -- 2.30.2